#include "PublicSendLuaData.h"
#include "CCLuaEngine.h"
#include "../Configs.h"
#include "../GameUtils.h"
#include "Device.h"

using namespace std;

PublicSendLuaData* PublicSendLuaData::m_instance = NULL;
PublicSendLuaData* PublicSendLuaData::getInstance(){
    if(!m_instance)
    {
        
        m_instance = new PublicSendLuaData();
    }
    return m_instance;
}
//获取变量名值
const char* PublicSendLuaData::getLuaVarString(const char* luaFileName,const char* varName){
    
    lua_State* ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();
    int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
    if(isOpen!=0){
        CCLOG("Open Lua Error isOpen: %i", isOpen);
        return NULL;
    }
    
    lua_settop(ls, 0);
    lua_getglobal(ls, varName);
    
    int statesCode = lua_isstring(ls, 1);
    if(statesCode!=1){
        CCLOG("Open Lua Error statesCode: %i", statesCode);
        return NULL;
    }
    
    const char* str = lua_tostring(ls, 1);
    lua_pop(ls, 1);
    
    return str;
}

const char* PublicSendLuaData::getLuaVarOneOfTable(const char* luaFileName,const char* varName,const char* keyName){
    
    lua_State*  ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();
    
    int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
    if(isOpen!=0){
        CCLOG("Open Lua Error: %i", isOpen);
        return NULL;
    }
    
    lua_getglobal(ls, varName);
    
    int statesCode = lua_istable(ls, -1);
    if(statesCode!=1){
        CCLOG("Open Lua Error: %i", statesCode);
        return NULL;
    }
    
    lua_pushstring(ls, keyName);
    lua_gettable(ls, -2);
    const char* valueString = lua_tostring(ls, -1);
    
    lua_pop(ls, -1);
    
    return valueString;
}
//执行Lua表，返回表结构
const char* PublicSendLuaData::getLuaVarTable(const char* luaFileName,const char* varName){
    lua_State*  ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();
    
    int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
    if(isOpen!=0){
        CCLOG("Open Lua Error: %i", isOpen);
        return NULL;
    }
    
    lua_getglobal(ls, varName);
    
    int it = lua_gettop(ls);
    lua_pushnil(ls);
    
    string result="";
    
    while(lua_next(ls, it))
    {
        string key = lua_tostring(ls, -2);
        string value = lua_tostring(ls, -1);
        
        result=result+key+":"+value+"\t";
        
        lua_pop(ls, 1);
    }
    lua_pop(ls, 1);
    
    return result.c_str();
}

//带参执行Lua方法有返回值
const char* PublicSendLuaData::callLuaFuncParReturn(const char* luaFileName,const char* functionName,__Array* arraypar,__Array* arraypartype){
    lua_State*  ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();
    
    bool have_traceback = false;
    lua_getglobal(ls, "__G__TRACKBACK__");
    if (lua_isfunction(ls, -1)) {
        have_traceback = true;
    } else {
        lua_pop(ls, 1);
    }   
    lua_getglobal(ls, functionName);
    int arg_count = (int)arraypar->count();
    for (size_t i = 0; i<arraypar->count(); i++) {
        __String* typestr = (__String*)arraypartype->getObjectAtIndex(i);
        __String* strnr = (__String*)arraypar->getObjectAtIndex(i);
        if(typestr->isEqual(String::create("string"))) {
            lua_pushstring(ls, strnr->getCString());
        } else if(typestr->isEqual(CCString::create("int"))) {
            lua_pushnumber(ls, strnr->intValue());
        } else if(typestr->isEqual(CCString::create("bool"))) {
            lua_pushboolean(ls, strnr->boolValue());
        }
    }

    if (lua_pcall(ls, arg_count, 1, have_traceback ? -arg_count - 2 : 0) == 0) {
        auto r = lua_tostring(ls, -1);
        lua_pop(ls, 1);
        return r;
    } else {
        if (have_traceback) {
            CCLOG("callLuaFuncParReturn error!\n");
            lua_pop(ls, 2);
        } else {
            CCLOG("callLuaFuncParReturn error!\n%s", lua_tostring(ls, -1));
            lua_pop(ls, 1);
        }
        return "";
    }
}

//带参执行Lua方法无返回值
const void PublicSendLuaData::callLuaFuncPar(const char* luaFileName,const char* functionName,__Array* arraypar,__Array* arraypartype){
    
    lua_State*  ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();
    
    lua_getglobal(ls, functionName);
    int countnum = (int)arraypar->count();
    for (size_t i = 0; i<arraypar->count(); i++) {
        __String* typestr = (__String*)arraypartype->getObjectAtIndex(i);
        __String* strnr = (__String*)arraypar->getObjectAtIndex(i);
        
        if(typestr->isEqual(CCString::create("string")))
        {
            lua_pushstring(ls, strnr->getCString());
        }
        else if(typestr->isEqual(String::create("int")))
        {
            lua_pushnumber(ls, strnr->intValue());
        }
        else if(typestr->isEqual(String::create("bool")))
        {
            lua_pushboolean(ls, strnr->boolValue());
        }
    }
    
    int traceback = 0;
    lua_getglobal(ls, "__G__TRACKBACK__");
    if (lua_isfunction(ls, -1)) {
        lua_insert(ls, -countnum -2);
        traceback = -countnum - 2;
    } else {
        lua_pop(ls, 1);
    }
    
    if (lua_pcall(ls, countnum, 0, traceback)) {
        if (traceback == 0) {
            CCLOG("PublicSendLuaData::callLuaFuncPar error: %s", lua_tostring(ls, - 1));
            lua_pop(ls, 1);
        } else {
            CCLOG("PublicSendLuaData::callLuaFuncPar error: %s", functionName);
            lua_pop(ls, 2);
        }
    }
}

const char* PublicSendLuaData::getFileFullPath(const char* fileName){
    const char* path = "";
    if (APP_TOLUAC == 1) {
        char tmp[128];
        snprintf(tmp, 128, "%s%s",fileName,"c");
        path = FileUtils::getInstance()->fullPathForFilename(tmp).c_str();
    }else{
        path = FileUtils::getInstance()->fullPathForFilename(fileName).c_str();
    }
    CCLOG("path=%s",path);
    return path;
}

PublicSendLuaData::~PublicSendLuaData(){
    
    CC_SAFE_DELETE(m_instance);
    m_instance=NULL;
}